﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.UI;
using crm_library.DataAccess.TableReps;
using System.Web.UI.WebControls;
using crm_library.Extenstions;
using System.Reflection;
using crm_library.DataAccess.ObjectReps;

namespace crm_library.Controls
{
	public class ListingTableFilter<T> : UserControl where T : ObjectRepresentation, new()
	{
		public enum ListingTableFilterType
		{
			TextBox,
			DropDownList,
			DateRange
		}

		private string ColumnName { get; set; }
		private string Label { get; set; }
		private Control Ctrl { get; set; }

		public ListingTableFilter(string columnName, string label, ListingTableFilterType ctrlType)
		{
			ColumnName = columnName;
			Label = label;

			switch (ctrlType)
			{
				case ListingTableFilterType.TextBox: Ctrl = new TextBox(); break;
				case ListingTableFilterType.DropDownList: Ctrl = new DropDownList(); break;
				default: throw new NotImplementedException("filter control type not implemented.");
			}

			Ctrl.ID = columnName + "_ctrl";
			Ctrl.ClientIDMode = System.Web.UI.ClientIDMode.Static;

		}


		public void AddListItemsToDDL(bool addDefaultAny = true, params ListItem[] items)
		{
			if (addDefaultAny) AddListItemToDDL(new ListItem("Any", "-1"), 0);
			items.Each(item => AddListItemToDDL(item));
		}
		public void AddListItemToDDL(ListItem item, int insertPosition = -1)
		{
			if (Ctrl is DropDownList)
			{
				if (insertPosition > -1)
				{
					(Ctrl as DropDownList).Items.Insert(insertPosition, item);
				}
				else
				{
					(Ctrl as DropDownList).Items.Add(item);
				}
			}
			else
			{
				throw new InvalidOperationException("filter - Attempted to add ListItem to non DropDownList");
			}

		}


		protected override void CreateChildControls()
		{
			base.CreateChildControls();

			var filterPane = new Panel
				{
					CssClass = "FilterPanel"
				};
			filterPane.Controls.Add((" " + Label + ": ").ToLiteral());
			filterPane.Controls.Add(Ctrl);

			this.Controls.Add(filterPane);
		}

		public PlaceHolder ToControl()
		{
			var place = new PlaceHolder();

			place.Controls.Add(ColumnName.ToLiteral());
			place.Controls.Add(Ctrl);

			return place;
		}

		public bool HasFilter
		{
			get
			{
				if (Ctrl is TextBox) return !String.IsNullOrEmpty((Ctrl as TextBox).Text);
				if (Ctrl is DropDownList) return !(String.Equals("-1", (Ctrl as DropDownList).SelectedValue, StringComparison.InvariantCultureIgnoreCase));
				throw new InvalidOperationException("Filter, invalid control type when checking HasFilter");
			}
		}

		public string FilterValue
		{
			get
			{
				if (!HasFilter) return "";
				if (Ctrl is TextBox) return (Ctrl as TextBox).Text;
				if (Ctrl is DropDownList) return (Ctrl as DropDownList).SelectedItem.Text;
				throw new InvalidOperationException("Filter, invalid control type when checking FilterValue");
			}
		}



		public bool MatchesItem(T Item)
		{
			if (!HasFilter) return true;

			var propertyInfoList = Item.GetType().GetProperties(BindingFlags.Public | BindingFlags.SetProperty | BindingFlags.Instance).ToList();

			foreach (var property in propertyInfoList)
			{
				var attributes = (ListingFieldAttribute[])property.GetCustomAttributes(typeof(ListingFieldAttribute), true);

				if (!attributes.Any()) continue;

				string name = property.Name;

				if (property.Name.Equals(ColumnName))
				{
					var value = property.GetValue(Item, null).ToString();

					return value.Contains(FilterValue, StringComparison.InvariantCultureIgnoreCase);
				}
			}

			return false;
		}
	}

	public static class CRUDFilterListExtensions
	{
		public static bool Matches<T>(this List<ListingTableFilter<T>> list, T item) where T : ObjectRepresentation, new()
		{
			foreach (var filter in list)
			{
				if (!filter.MatchesItem(item)) return false;
			}

			return true;
		}



		public static Table ToFilterList<T>(this List<ListingTableFilter<T>> list) where T : ObjectRepresentation, new()
		{
			var tbl = new Table();

			for (int index = 0; index < list.Count; index += 3)
			{
				int range = Math.Min(3, list.Count - index);
				var subList = list.GetRange(index, range);

				if (subList.Count == 0) break;
				if (subList.Count == 1) tbl.AddGeneratedRow(subList[0]);
				if (subList.Count == 2) tbl.AddGeneratedRow(subList[0], subList[1]);
				if (subList.Count == 3) tbl.AddGeneratedRow(subList[0], subList[1], subList[2]);
			}

			return tbl;
		}




	}
}
